package com.acme.bankapp.domain.bank;

/**
 * Abstract account contains information about balance
 * Account contains link to client. This bidirectional relation was added for training purpose
 * Two accounts are equal when and only when clients that have these account are also equal.
 * In accordance to {@code equals()} {@code hashCode()} return value depends only on client.
 * @author Artem Nikitin
 *
 */
public abstract class AbstractAccount implements Account {

	protected double balance;
	
	/**
	 * Bidirectional link was added for training purpose.
	 */
	private Client client;

	/**
	 * Constructs a new account with specified balance
	 * @param amount - balance
	 */
	public AbstractAccount(final double amount) {
		if (amount < 0) {
			throw new IllegalArgumentException("Balance cannot be negative");
		}
		this.balance = amount;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + ((getClient() == null) ? 0 : getClient().hashCode());
		return result;
	}
	
	/**
	 * Two accounts are equal when clients that have these accounts are equal.
	 */
	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		AbstractAccount other = (AbstractAccount) obj;
		if (getClient() == null) {
			if (other.getClient() != null)
				return false;
		} else if (!getClient().equals(other.getClient()))
			return false;
		return true;
	}

	public double getBalance() {
		return balance;
	}

	public abstract void deposit(final double amount);

	public abstract void withdraw(final double amount) throws NotEnoughFundsException;
	
	public Client getClient() {
		return client;
	}

	/**
	 * Set link to client who has this account. Client cannot be {@code null} 
	 * @param client - client
	 * @throws IllegalArgumentException - If client is {@code null}
	 */
	public void setClient(Client client) {
		if (client == null) {
			throw new IllegalArgumentException("Client must be not null");
		}
		this.client = client;
	}

	@Override
	public String toString() {
		return "Balance: " + getBalance();
	}

	public long decimalValue() {
		return Math.round(getBalance());
	}

}
